package Server;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import Agent.Agent;
import Agent.ObjectAgent;
import MachineLearning.LinearRegression;
import SLA.SLA;
import Session.Session;

public class Server {
	
	public ArrayList<ObjectAgent> freeAgents;
	private static final Logger LOG = Logger.getLogger(Server.class.getName());
	public static int countThreads;
	
	
	public Server() throws SecurityException, IOException {
		freeAgents = new ArrayList<ObjectAgent>();
		Handler file = new FileHandler("Logger.txt");
		file.setLevel(Level.ALL);
		LOG.addHandler(file);
		LOG.setUseParentHandlers(false);
		
	}
	
	public void registerAgents(String registerOfAgents) throws NumberFormatException, IOException, NotBoundException{		
	    BufferedReader in = new BufferedReader(new FileReader(registerOfAgents));
	    String[] informationAgent;
	    String str;
	    ObjectAgent obj;
	    while (in.ready()) {
	    	if((str = in.readLine())!=null){
	    		informationAgent = str.split(" ");
	    		obj = new ObjectAgent(Integer.parseInt(informationAgent[1]),informationAgent[2],informationAgent[3]);
	    		System.out.println("Agente "+informationAgent[1]+" "+informationAgent[2]+" "+informationAgent[3]+" foi registrado!");
	    		LOG.fine("Agente "+informationAgent[1]+" "+informationAgent[2]+" "+informationAgent[3]+" foi registrado!");
	    		freeAgents.add(obj);
	    	}
	    }
		in.close();
	}
	    
	public void dispatchQuery(String inputPath,ArrayList<String> transaction,int numAgents, LinearRegression machine) throws NumberFormatException, NotBoundException, IOException, SecurityException, ClassNotFoundException, SQLException{
		
		Remote obj = null;
		String[] s;
		ObjectAgent objAgent = null;
		String[] informationAgent;
        BufferedReader in = new BufferedReader(new FileReader(inputPath));
        String str;
        int index;
        
        int i = 0;
        int j = transaction.size()/numAgents;
     
        Session sessionClient = new Session(this);
        
        while (in.ready()) {
        	if((str = in.readLine())!=null){
        		System.out.println(str);
        		if(str.startsWith("agent")){
        			informationAgent = str.substring(6).split(" ");
        			System.out.println("AGENTE:"+informationAgent[0]+" "+informationAgent[1]+" "+informationAgent[2]);
        			objAgent = new ObjectAgent(Integer.parseInt(informationAgent[1]),informationAgent[0],informationAgent[2]);
        			obj = LocateRegistry.getRegistry(informationAgent[0],Integer.parseInt(informationAgent[1])).lookup(informationAgent[2]);
        			if(!sessionClient.getAgents().contains(objAgent))sessionClient.addAgent(objAgent);
        			
		  		}
        		else if(str.startsWith("sla")){
        			s = str.substring(4).split(" ");
        			SLA sla = new SLA(new Float(s[0]), new Float(s[1]),Integer.parseInt(s[2]), new Float(s[3]), new Float(s[5]),new Float(s[6]),
        						Integer.parseInt(s[7]));
        			
        			objAgent.setSla(sla);
        			
        			i=1;
        			ArrayList<String> queries = new ArrayList<String>();
        			while(!transaction.isEmpty() && i<j){
        				queries.add(transaction.remove(0));
        				i++;
        			}
        			if(transaction.size()<j) queries.addAll(transaction);
        			
        			objAgent.setTransaction(queries);     
        			objAgent.setMachine(machine);
        			
        			index = sessionClient.getAgents().indexOf(objAgent);
        			sessionClient.index = index;
        			
        			Thread t = new Thread(sessionClient);
        			t.start();
        			
        		}
        		else if(str.startsWith("wait")){
        			j = transaction.size()/numAgents;
        			
        			sessionClient = new Session(this);
        		}
        	}
        }
      
        in.close();
	}
	
	public synchronized ObjectAgent getFreeAgent() {
		boolean first = true;
		while(freeAgents.isEmpty()){
			if(first){
				System.out.println("Esperando por agente disponivel...");
				first = false;
			}
		}
		return freeAgents.remove(0);
	}
	
	public void addFreeAgent(ObjectAgent agent) throws AccessException, RemoteException, NotBoundException{
		freeAgents.add(agent);
		Remote obj = LocateRegistry.getRegistry(agent.getIp(),agent.getPort()).lookup(agent.getAgentName());
		((Agent) obj).setOn(false);
		System.out.println("O agente "+agent.getAgentName()+" voltou a ser disponivel...");
	}

}
